#!/usr/bin/perl
#
# Process an user update that comes as a Web form
# This is the admin version 
#

use Counter;
use FileTable;
use POSIX;
use Validate::Persons;
use Counter::CGI;
use CGI::Carp;
use ErrorForm;
use Encode;
require "isemail.pl";

$] > 5.008 && binmode(STDOUT, ":utf8"); # set web page output to utf-8

open(LOG, ">>logs/eventlog");
print LOG scalar(localtime), " userupdate.cgi\n";
$| = 1; # fast flush (debug)

$q = new Counter::CGI;

for $name ($q->param()) {
    if ($] > 5.008 && !Encode::is_utf8($q->param($name))) {
	$entry{$name} = Encode::decode("utf-8", $q->param($name));
    } else {
	$entry{$name} = $q->param($name);
    }	
}

# Try to process command
$users = Counter::open(O_RDWR);
$persons = FileTable::open("db/persons", O_RDWR);

($key = $entry{key}) =~ s/-.*//;
$user = $users->get($key);

if (!$user) {
    die "ERROR: No user record for $key ($entry{$key})\n";
}



$otheruser = $users->getbyemail($entry{sendreplyto});
if ($otheruser) {
    if ($otheruser->key() ne $user->key()) {
	my $otherkey = $otheruser->key();
	warn "Mismatch: User->key:", $user->key, ", otheruser->key:", $otheruser->key(), "!\n";
	print <<EoF;
Content-type: text/html; charset="utf-8"

<HTML><HEAD><TITLE>Linux Counter Admin Update: Collision</TITLE></HEAD>
<BODY bgcolor=white>
<H1><img src="/gifs/Logo-small.png" alt="Linux Counter Logo">Collision</H1>
The email $entry{sendreplyto} belongs to entry
<a href="/cgi-bin/adm/display-person.cgi?user=$otherkey">#$otherkey</a>.<p>
The current record is #$key. Merge them using the "Merge" field on the
person display page, if that is the Right Thing.
</BODY></HTML>
EoF
       exit(0);
    }
}


#
# Start off the HTML. Anything that happens is recorded in a comment
#
print "Content-type: text/html; charset=\"utf-8\"\n\n";

print "<HTML><HEAD><TITLE>Linux Counter Admin Update Ack</TITLE></HEAD><BODY>\n";
print "<!--\n"; # Comment to hide the trace stuff

for $key (sort(keys(%entry))) {
    print "$key: $entry{$key}\n";
}

# Removed - this is the ADMIN userupdate
#if ($user->{key} ne $entry{key}) {
#    print "SECURITY ERROR: Key doesn't match\n";
#    warn "SECURITY ERROR: Key doesn't match\n";
#    $userkey = $user->{key};
#    warn "Is $entry{key} should have been $userkey\n";
#    print LOG "userupdate: $entry{$key} is not $userkey\n";
#    exit 1;
#}
push(@sendackto, $user->{email});

# Find action. I don't like this, but it's what works...
if ($entry{"delete"}) {
    print "Action: DELETE\n";
    $person = $persons->get($key);
    if ($user && $person) {
	$person->delete;
	delete $user->{person};
	$user->store;
	print LOG "Person $key deleted by $ENV{REMOTE_USER}\n";
    } elsif ($user && !$person) {
	warn "Deleting deleded person $key\n";
        print <<EoF;
-->
Entry has already been deleted. Nothing more needs to be done.
</body></html>
EoF
	exit 0;
    } else {
	warn "User or person not found for $key\n";
	exit 1;
    }
    # NOTE: we do NOT send email on admin delete
    print "-->\n";
    print <<EoF;
<h1>This entry has been deleted</h1>
This person info has been deleted from the Linux Counter.
It will not be included in the count of Linux users.
<p>
NOTE: The user has NOT been informed.
<p>
<a href="/index.php"><img src="/gifs/shark-gull.gif"> Back to main page</a>
</body></html>
EoF

} else {
    if ($entry{"enter"}) {
	warn "adm/userupdate action ENTER\n";
    } else {
	warn "adm/userupdate action DEFAULT\n";
    }
    print "Action: ENTER\n";
    $dosendemail = 0; # By default, don't send email on update
    $user = $users->get($key);
    if (!$user) {
	warn "userupdate: key $key not found\n";
	print LOG "No update on $key - not found in users\n";
	print "key $key not found in users!\n";
	# NOTE: Printout of error form is missing.....
	exit 1;
    } elsif ($entry{sendreplyto} && $entry{sendreplyto} ne $user->{email}
	     || $entry{comment} && $entry{comment} ne $user->{comment} ) {
	warn "adm/userupdate changing USER record\n";
	if ($entry{sendreplyto} && $entry{sendreplyto} ne $user->{email}) {
	    print "Changing USER email to $entry{sendreplyto}\n";
	    push(@sendackto, $entry{sendreplyto});
	    print LOG "User ", $user->key,
		 " email changed to $entry{sendreplyto}\n";

	    $user->{email} = $entry{sendreplyto};
	    $dosendemail = 1;
	}
	$user->{comment} = $entry{comment};
	addadmin($user);
	# NOTE: No guard against the error of setting it to someone
	# else's email....store will crash...
	# but this should have been trapped earlier in the script.
	$user->store;
    }
    # An user may want to add himself even if he's not present
    $person = $persons->get($key, O_CREAT);
    
    for $field ($persons->fields) {
	if ($entry{$field}) {
	    if ($person->{$field}) {
		if ($person->{$field} ne $entry{$field}) {
		    my $uf = $person->{$field};
		    print "Changing $field from $uf to $entry{$field}\n";
		}
	    } else {
		print "Adding $field: $entry{$field}\n";
	    }
	} elsif ($person->{$field}) {
	    print "Deleting $field\n";
	}
	$person->{$field} = $entry{$field};
    }
    # Clean up the record
    my $recordempty = 1;
    for $field ($person->fields) {
	if ($person->{$field} eq "") {
	    delete $person->{$field};
	} else {
	    $recordempty = 0;
	}
    }
    if (!$recordempty) {
	addadmin($person);
	print LOG "Person $key updated by $ENV{REMOTE_USER}\n";
	$person->store;
	if ($user->{person} ne "y") {
	    $user->{person} = "y";
	    $user->store;
	}
    } else {
	print LOG "Empty person record not stored for $key\n";
    }
    # E-mail ack of change
    if ($dosendemail) {
	# FIXME: No check that sendackto is legal email
	$hasnot = "has";
	system("tools/sendemail", "$key", @sendackto);
    }
    print "-->\n"; # End comment around script trace    
    $sendackto = join(" and ", @sendackto);
    print <<EoF;
<h1>The record is updated</h1>
<p>
EoF
    if ($dosendemail) {
	print <<EoF;
An acknowledge message $hasnot been sent to $sendackto
<p>
EoF
    }
    print <<EoF;
If there are any problems with the counter, don't hesitate to contact
Help&#x40;Counter.li.org
<p>
<a href="https://counter.li.org/adm/update.php"><img src="/gifs/shark-gull.gif"> Back to update page</a><br>
<a href="/index.php"><img src="/gifs/shark-gull.gif"> Back to main page</a>
<br>
<a href="/cgi-bin/adm/display-person.cgi?user=$key"><img src="/gifs/shark-gull.gif"> Back to user record</a>
</body></html>
EoF
} # end of ENTER branch of update

exit 0;

# Add admin fields - recdate and method - to a record
sub addadmin {
    my $record = shift;

    $record->{recdate} = scalar(localtime);
    $record->{method} = "admin";
    $record->{ident} = "script=$0 ip=$ENV{REMOTE_ADDR} user=$ENV{REMOTE_USER}";
}

    
   
